﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../global/head.h"
#include "node_impl.h"
#include "doc_impl.h"

namespace xos_xml
{
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static doc_impl::POOL * pool_ptr = 0;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    doc_impl::doc_impl()
    {
    }

    doc_impl::~doc_impl()
    {
        term();
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // public method

    int doc_impl::get_addr( POOL *** pppPool, LIST *** pppList )
    {
        int ret = 0;
        if( pppPool )
        {
            *pppPool = &pool_ptr;
        }
        if( pppList )
        {
            *pppList = 0;
        }
        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // i_xml_node method

    // 
    // 载入XML
    // 
    int doc_impl::load_xml_string( const char * lpszXml )
    {
        int nRet = 0;

        if( 0 == nRet )
        {
            if( !lpszXml || ( 0 == strlen( lpszXml ) ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            m_doc.Clear();

            if( !m_doc.Parse( lpszXml, 0, TIXML_ENCODING_UTF8 ) )
            {
                nRet = 1;
            }
        }

        return nRet;
    }

    int doc_impl::load_xml_file( const char * lpszXml )
    {
        int nRet = 0;

        if( 0 == nRet )
        {
            if( !lpszXml || ( 0 == strlen( lpszXml ) ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            m_doc.Clear();

            if( !m_doc.LoadFile( lpszXml, TIXML_ENCODING_UTF8 ) )
            {
                nRet = 1;
            }
        }

        return nRet;
    }

    // 
    // 保存XML
    // 
    int doc_impl::save_xml_string( char * lpszXml, int nLen, int * lpnLenNeeded )
    {
        using namespace std;

        int nRet = 0;

        TiXmlPrinter print;
        int nSize = 0;

        if( 0 == nRet )
        {
            print.SetIndent( "\t" );
            m_doc.Accept( &print );

            nSize = ( int )print.Size();

            if( lpnLenNeeded )
            {
                *lpnLenNeeded = nSize + 1;
            }
        }

        if( 0 == nRet )
        {
            if( !lpszXml || ( nSize > nLen - 1 ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            g_pSysData->m_pContainer->crt()->strcpy( lpszXml, nLen, print.CStr() );
        }

        return nRet;
    }

    int doc_impl::save_xml_file( const char * lpszFile )
    {
        int nRet = 0;

        if( 0 == nRet )
        {
            if( lpszFile )
            {
                m_doc.SaveFile( lpszFile );
            }
            else
            {
                m_doc.SaveFile();
            }
        }

        return nRet;
    }

    // 
    // 返回根节点
    // 
    int doc_impl::get_root_node( i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlElement * pRet = 0;

        if( 0 == nRet )
        {
            if( !ppv )
            {
                nRet = 1;
            }
            else
            {
                *ppv = 0;
            }
        }

        if( 0 == nRet )
        {
            pRet = m_doc.FirstChildElement();

            if( !pRet )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = false;
            p->m_pNode = pRet;
            *ppv = p;
        }

        return nRet;
    }

    // 
    // 节点
    // 
    int doc_impl::create_and_append_node( const char * lpszNodeName, i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlNode * pNode = 0;

        if( 0 == nRet )
        {
            if( !ppv )
            {
                nRet = 1;
            }
            else
            {
                *ppv = 0;
            }
        }

        if( 0 == nRet )
        {
            if( !lpszNodeName || ( 0 == strlen( lpszNodeName ) ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            pNode = m_doc.InsertEndChild( TiXmlElement( lpszNodeName ) );

            if( !pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = false;
            p->m_pNode = pNode->ToElement();
            *ppv = p;
        }

        return nRet;
    }

    int doc_impl::create_node( const char * lpszNodeName, i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlElement * pNode = 0;

        if( 0 == nRet )
        {
            if( !ppv )
            {
                nRet = 1;
            }
            else
            {
                *ppv = 0;
            }
        }

        if( 0 == nRet )
        {
            if( !lpszNodeName || ( 0 == strlen( lpszNodeName ) ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            pNode = new TiXmlElement( lpszNodeName );

            if( !pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = true;
            p->m_pNode = pNode;
            *ppv = p;
        }

        return nRet;
    }

    int doc_impl::append_node( i_xml_node * pv )
    {
        int nRet = 0;

        TiXmlNode * pNode = 0;
        node_impl * p = 0;

        if( 0 == nRet )
        {
            if( !pv )
            {
                nRet = 1;
            }
            else
            {
                p = static_cast< node_impl * >( pv );
            }
        }

        if( 0 == nRet )
        {
            pNode = m_doc.LinkEndChild( p->m_pNode );

            if( pNode != p->m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            p->m_bHasOwner = false;
        }

        return nRet;
    }

    int doc_impl::remove_node( i_xml_node * pv )
    {
        int nRet = 0;

        node_impl * p = 0;

        if( 0 == nRet )
        {
            if( !pv )
            {
                nRet = 1;
            }
            else
            {
                p = static_cast< node_impl * >( pv );
            }
        }

        if( 0 == nRet )
        {
            bool bRet = m_doc.RemoveChild( p->m_pNode );

            if( !bRet )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            p->m_bHasOwner = false;
            p->init();
        }

        return nRet;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //

    int doc_impl::init()
    {
        int nRet = 0;
        m_doc.SetCondenseWhiteSpace( false );
        return nRet;
    }

    int doc_impl::term()
    {
        int nRet = 0;
        m_doc.Clear();
        return nRet;
    }

} // xos_xml
